#!/usr/bin/env python
#-*- coding: utf-8 -*-

import argparse, re, random

def parse_file(filename, voter):
    try:
        with open(filename, 'r') as f:
            d = [line.strip() for line in f.readlines()]
    except:
        print "Error: File '{0}' not found.".format(filename)
        return

    ddict = re.compile(r'\s*(?P<candidates>\d+)\s*(?P<voters>\d+)').match(d[0]).groupdict()
    candidates, voters = int(ddict['candidates']), int(ddict['voters'])

    if voter >= voters:
        print "Error: There are only {0} voters (0 ... {1})".format(voters, voters-1)
        return

    ## read preference relation lines
    RE_number = re.compile(r'\d+')
    prefs = [[int(e) for e in re.findall(RE_number, line)] for line in d[1:voters+1]]
    
    return prefs


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='I Lie. Do I? I Spoke The Truth. Did I? I Do.')
    parser.add_argument('relations', type=str, nargs=1,
                        help='A file containing the voters’ preference relations')
    parser.add_argument('voter', type=int, nargs=1,
                        help='Index of the voter whose preference relation should be printed')
    parser.add_argument('method', type=str, nargs=1,
                        choices=['plurality', 'irv', 'borda'],
                        help='The election method')
    args = parser.parse_args()
    random.seed()
    prefs = parse_file(args.relations[0], args.voter[0])


    randomchoice = random.random()

    ## with 10% chance, return the true preference relation (=don’t lie)
    if randomchoice < 0.1:
        print " ".join([str(i) for i in prefs[args.voter[0]]])
    else:
        mypref, otherprefs = prefs[args.voter[0]], prefs[:args.voter[0]]+prefs[args.voter[0]+1:]

        ## plurality
        if args.method[0] == 'plurality':
            first_choices = [p[0] for p in otherprefs]  # preferred candidates
            first_votes   = [first_choices.count(i) for i in range(len(mypref))]  # no. of first votes
            front_runners_votes = sorted(first_votes)[::-1][:2]
            first, second = front_runners_votes[0], front_runners_votes[1]
            if first == second:  # draw between front runners
                f = first_votes.index(first)
                front_runners = [f, 1 + f + first_votes[f+1:].index(first)]
            else:  # two distinct front runners
                front_runners = [first_votes.index(first), first_votes.index(second)]
            i, j = mypref.index(front_runners[0]), mypref.index(front_runners[1])
            my_favourite =  min(i, j)
            print " ".join([str(i) for i in [mypref[my_favourite]] + mypref[my_favourite+1:] + mypref[:my_favourite]])

        ## instant runoff voting (IRV, ger. „Pluralitätswahl mit übertragbaren Stimmen“)
        elif args.method[0] == 'irv':
            first_choices = [p[0] for p in otherprefs]  # preferred candidates
            first_votes   = [first_choices.count(i) for i in range(len(mypref))]  # no. of first votes
            if len(mypref) < 3 or sorted(first_votes)[-1] >= len(prefs)/2:
                print " ".join([str(i) for i in prefs[args.voter[0]]])
            else:
                def irv(new_p):
                    pp = [p[:] for p in otherprefs + [new_p]]
                    while True:
                        #~ print ""
                        #~ for p in pp: print p
                        choices = [p[0] for p in pp]
                        votes   = [(choices.count(i), i) for i in pp[0]]
                        #~ print "vote counts are", sorted(votes)
                        if sorted(votes)[-1][0] >= len(pp)/2:  # majority reached
                            return [sorted(votes)[-1][1], sorted(votes)[-1][0]]
                        else:
                            loser = sorted(votes)[0][1]
                            #~ print "eliminate", loser
                            for p in pp: p.remove(loser)
                pref, maxv = mypref, 0
                rest = mypref[3:]
                for i in range(len(mypref)):
                    if i in rest: continue
                    for j in range(len(mypref)):
                        if i==j or j in rest: continue
                        for k in range(len(mypref)):
                            if k==i or k==j or k in rest: continue
                            winner, votes = irv([i, j, k]+rest)
                            if votes > maxv and winner == mypref[0]:
                                #~ print "good choice!", votes, [i, j, k]+rest, irv([i, j, k]+rest)
                                pref, maxv = [i, j, k]+rest, votes
                print " ".join([str(i) for i in pref])

        ## borda method
        elif args.method[0] == 'borda':
            maxpoints = len(mypref) - 1
            points = [0 for i in range(maxpoints+1)]
            for p in otherprefs:
                for (i, c) in enumerate(p):
                    points[c] += maxpoints-i
            points_with_me = points[:]
            for (i, c) in enumerate(mypref):
                points_with_me[c] += maxpoints-i
                
            if points_with_me.index(max(points_with_me)) == mypref[0]:
                ## my favourite wins with my true preference (provided the other voters don’t lie... but that way lies madness)
                print " ".join([str(i) for i in mypref])#
            else:
                ##trololol
                if len(mypref) <= 3:
                    ##i have no idea what i’m doing
                    print " ".join([str(i) for i in mypref])
                else:
                    ##oh god why ಠ_ಠ
                    print " ".join([str(mypref[2])]+[str(mypref[0])]+[str(mypref[1])]+[str(i) for i in mypref[3:]])
 
""" 
                        ,L#############################i                
               j#######Et       .jW#WGfjG##;           i##              
          :###                   .fE###WL,     Wj         ##            
        ##i                                   E#   #       ##E          
      ##       .#       t#         E           #  #   ,     ##:         
      #L                 ,                        ,  #       i#         
     ##                  j           ###########W             .#;       
   ###         ###G#####i         ###     #####; ## .       :i. ##;     
 E## WK         ;G###########     ## W###G      K## G            if##   
W#K, iL                  #          j       ##       G###   j##     i#. 
##     E:   :#####      j#                     .fGGi     ##    D#  f  #:
i#        K#          ###          ##K E              ######i   ## j  ##
 ###  W   ##       E###               #          i####    ##K## #  W  #E
  ##  #  ####   #     ,#      ,Ef.t#;##     L######      ##    #  .  ## 
   ##   L### ###W        ##D        f#####i      ##j######     jL  ##   
    ##  ###  #  .#################W:   ##     t#####  D#L       fE#     
    ##  ######  ##     ;#,    ##        ########i##  ##        ##f      
    ##  f##################################K     .####         #        
    ##   ############################j  E#       ###          #:        
    ##   ## #i##.W###DK###;,    #        ##   ###           ##.         
    #j    ###K K#; ##    #      #         ####            ##K           
    #       #######E##   ##     ##########    ;#   ##  K##              
   G#               .tGEW####EGf,         ,#   ##   ###                 
   ##   #    #                        #f  ##    ###K                    
   ##    ij                       L#.      ###W                         
   ##          tfGGGft;.               D##E                             
    j#i                        :#######                                 
      G##G               f######L                                       
          G###########E,                                                
"""
 
 
